//  默认情况下，直接使用  webpack  .\src\main.js   .\dist\bundle.js 就能实现项目的构建了；
// 但是，如果只运行  webpack 命令的话，需要在项目的根目录中 ，创建 `webpack.config.js` 的文件；
// 而且，在这个配置文件中，必须显示声明   要处理文件的路径  和  输出的文件的路径

const path = require('path');
// 导入把 HTML 页面生成到内存中的插件
const htmlWebpackPlugin = require('html-webpack-plugin');// 导入的是一个构造函数
// 导入删除文件夹的插件
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
// 导入 webpack 这个模块
const webpack = require('webpack');
// 导入抽取CSS样式文件的插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 导入样式压缩插件
const OptimizeCssPlugin = require('optimize-css-assets-webpack-plugin');
// 导入js压缩插件
let UglifyjsPlugin = require('uglifyjs-webpack-plugin');

// 注意： 这里使用Node中的语法，向外暴露了一个配置对象
// 因为 webpack 这个构建工具，底层就是使用 Node.js 开发出来的
module.exports = {
    entry: {
        app: path.join(__dirname, './src/main.js'), // 这是项目的主入口文件
        // vendors: ['jquery'] // 这是第三方包的名称
    }, // 项目的入口文件
    output: { // 指定输出文件的配置
        path: path.join(__dirname, './dist'), // 指定输出文件的存放路径
        filename: 'index.js' // 指定输出文件的名称
    },
    plugins: [ // 插件的数组
        new htmlWebpackPlugin({ // 创建一个把HTML首页托管到内存中的插件
            template: path.join(__dirname, './src/index.html'), //  要把哪个HTML页面，作为模板，复制一份托管到内存中
            filename: 'index.html' // 指定将来在内存中复制出来的页面，名称叫做 index.html
        }),
        new CleanWebpackPlugin(),
        new MiniCssExtractPlugin({
            filename: 'css/styles.css', // 抽取CSS文件到单独的目录中
        }),
        // new OptimizeCssPlugin() // 压缩css文件
    ],
    module: { // 用来配置 非JS文件对应的loader的
        rules: [ // 就是这些 非 JS 文件 和 loader 之间的对应关系
            {test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader' ]}, // 创建处理 css 文件的 loader 匹配规则
            {test: /\.less$/, use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'less-loader']}, // 配置处理less文件的规则
            {test: /\.scss$/, use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader']}, // 配置 处理 scss 文件的规则
            // { test: /\.jpg|png|gif|bmp$/, use: ['url-loader'] }, // 配置 处理 样式表中图片的 loader规则

            // 可以给url-loader传参数
            // 若不给参数，则会自动将图片路径转换成base64格式，而且图片名变成32位的hash码，而且同名的两张不同图片也会转换成不同的hash码，从而防止出现重名；
            // limit 表示图片大小，单位是byte，若图片的大小小于该值，则会转换成base64，否则不会转换，图片路径还是原来的路径；
            // name 图片名，name=[name].[ext]，表示保留原来的图片名和图片格式，
            // 但是如果有两张图重名，则会发生覆盖，所以为解决该问题，可以将图片自动生成的hash码前8位加到原图片名上，这样既可以保留原图片名，又可以防止重名。
            {test: /\.jpg|png|gif|bmp$/, use: 'url-loader?limit=7631&name=images/[hash:8]-[name].[ext]'},

            // 添加转换JS文件的loader，其中，必须把 node_modules 目录设置为 排除项，这样，在打包的时候，会忽略node_modules 目录下的所有JS文件；否则项目运行不起来！
            {test: /\.js$/, use: 'babel-loader', exclude: /node_modules/},
        ]
    },
    optimization: {
        // minimize: true, // 默认是true,即默认压缩js代码，可以不用写出来
        minimizer: [
            new UglifyjsPlugin({
                cache: true // 使用缓存 也可以放到上面的plugins数组中
            }),
            new OptimizeCssPlugin() // 也可以放到上面的plugins数组中
        ],
        splitChunks: {
            chunks: 'async',
            minSize: 30000,  // 大于30kb的文件才会分割
            minChunks: 1, // 模块最少使用次数，若值为2，则只应用了一次的模块步做分割打包处理
            maxAsyncRequests: 5, // 同时加载的模块数量最大值
            maxInitialRequests: 3, // 首次加载引入模块可分割的最大值
            name: true,
            cacheGroups: {  // 缓存组，将所有加载模块放在缓存里面一起分割打包
                vendor: { // 自定义打包模块
                    name: 'vendor',
                    chunks: 'all',
                    priority: -10, // 优先级，先打包到哪个组，值越大，优先级越高
                    reuseExistingChunk: false, // 模块嵌套引入时，判断是否复用已经打包的模块
                    test: /[\\/]node_modules[\\/]/,
                    filename: 'vendors.js'
                },
                default: { // 默认打包模块
                    minChunks: 2,
                    priority: -20,
                    reuseExistingChunk: true
                }
            }
        }
    }
}